package com.gooluke.common.util;

import com.gooluke.common.enums.BasicError;
import com.gooluke.common.exception.BizException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author gooluke
 * description 异常工具类，用于抛出异常
 * datetime 2025-03-28 15:59
 */
public class ExceptionUtil {

    private static final Logger log = LoggerFactory.getLogger(ExceptionUtil.class);

    public static void throwDefaultException() {
        throwDefaultException("系统繁忙，请稍后重试~");
    }

    public static void isTrue(boolean expression, String message) {
        if (!expression) {
            throwDefaultException(message);
        }
    }

    public static void throwDefaultException(String message) {
        logCallerInfo(message);
        throw new BizException(message);
    }

    public static void throwDefaultException(BasicError basicError) {
        throw new BizException(basicError.getMessage());
    }

    public static void throwException(BasicError basicError) {
        if (basicError.getException() == null) {
            throwDefaultException(basicError);
        }
        try {
            logCallerInfo(basicError.getMessage());
            throw basicError.getException().getDeclaredConstructor(String.class).newInstance(basicError.getMessage());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 打印调用者的类、方法、行号等信息
     */
    private static void logCallerInfo(String message) {
        try {
            // 获取当前线程的调用栈
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            // 0: getStackTrace
            // 1: logCallerInfo
            // 2: throwDefaultException / throwException
            // 3: 调用 ExceptionUtil 的方法（我们真正关心的调用者）
            if (stackTrace.length >= 4) {
                StackTraceElement caller = stackTrace[3];
                log.error("{}.{} (Line: {}) - {}", caller.getClassName(), caller.getMethodName(), caller.getLineNumber(), message);
            }
        } catch (Exception e) {
            //doNothing
        }
    }

}
